import type {
  IPostComment,
  IPostCommentChildReply,
  IPostCommentParentReply,
  IPostCommentReply,
} from '@/interfaces';
import { type ChangeEvent, useContext, useEffect, useState } from 'react';
import { useInfiniteQuery, useMutation } from '@tanstack/react-query';
import useToast, { LoginReminderContent } from '@/hooks/useToast';
import {
  createChildReply,
  queryAllChildReplyByParentReplyId,
} from '@/services/api';
import sanitizeHtml from 'sanitize-html';
import Image from 'next/image';
import { getUserAvatar, toRelativeTime } from '@/lib/tool';
import Link from 'next/link';
import ChildReply from '@/app/[locale]/posts/[id]/ChildReply';
import { AppContext } from '@/contexts/app';
import { PostIdPageContext } from '@/contexts/post-id';
import Spinner from '@/app/[locale]/component/spinner/spinner';

export default function ParentReply({
  parentReplyItem,
  parentReplyIndex,
  replyItem,
  replyIndex,
  commentItem,
  commentIndex,
}: {
  parentReplyItem: IPostCommentParentReply;
  parentReplyIndex: number;
  replyItem: IPostCommentReply;
  replyIndex: number;
  commentItem: IPostComment;
  commentIndex: number;
}) {
  const context = useContext(PostIdPageContext)!;
  const {
    source: { path },
    translatedFields,
  } = context;
  const appContext = useContext(AppContext);
  const metadata = appContext.metadata!;
  const env = metadata.env;
  const [replyContent, setReplyContent] = useState('');
  const { show } = useToast();
  const [pages, setPages] = useState<IPostCommentChildReply[]>(
    parentReplyItem.content,
  );
  const queryKey = [
    '/forum',
    '/replies',
    parentReplyItem.reply.id,
    '/child',
    'infinite',
  ];

  const createChildReplyMutation = useMutation(createChildReply);

  const replyQuery = useInfiniteQuery(
    queryKey,
    async (context) => {
      return (await queryAllChildReplyByParentReplyId({
        id: context.queryKey[2],
        query: context.pageParam,
      })) as IPostCommentParentReply;
    },
    {
      keepPreviousData: true,
      getPreviousPageParam: (firstPage) => {
        if (!firstPage.pageable.previous) {
          return;
        }
        return {
          page: Math.max(firstPage.pageable.page - 1, 0),
        };
      },
      getNextPageParam: (lastPage) => {
        if (!lastPage.pageable.next) {
          return;
        }
        return {
          page: Math.min(lastPage.pageable.page + 1, lastPage.pageable.pages),
        };
      },
      initialData: () => {
        return {
          pages: [parentReplyItem],
          pageParams: [{ page: 0 }],
        };
      },
    },
  );

  useEffect(() => {
    if (replyQuery.data) {
      setPages(
        replyQuery.data.pages
          .flatMap((item) => item.content)
          .map((item) => {
            item.reply._createdOnText = toRelativeTime(item.reply.createdOn);
            return item;
          }),
      );
    }
  }, [replyQuery.data]);

  async function onClickPostReply() {
    try {
      if (!path.user) {
        show({
          title: translatedFields.notLoggedInPrompt,
          content: <LoginReminderContent />,
        });
        return;
      }

      const _replyContent = replyContent.trim();
      if (!_replyContent) {
        show({
          type: 'DANGER',
          message: translatedFields.replyContentEmptyError,
        });
        return;
      }

      const content = sanitizeHtml(_replyContent);
      if (!content) {
        show({
          type: 'DANGER',
          message: translatedFields.replyContentEmptyError,
        });
        return;
      }

      const parentReplyId = parentReplyItem.reply.id;
      await createChildReplyMutation.mutateAsync({
        data: {
          parentReplyId,
          content,
        },
      });

      await replyQuery.refetch({ throwOnError: true });

      setReplyContent('');
      show({
        type: 'SUCCESS',
        message: translatedFields.replyCompleted,
      });
    } catch (e) {
      createChildReplyMutation.reset();
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  async function onClickLoadMore() {
    try {
      await replyQuery.fetchNextPage();
    } catch (e) {
      show({
        type: 'DANGER',
        message: e,
      });
    }
  }

  function onChangeReplyContent(e: ChangeEvent<HTMLTextAreaElement>) {
    setReplyContent(e.target.value);
  }

  return (
    <PostIdPageContext.Provider value={{ ...context, queryKey }}>
      <div className="vstack gap-4">
        <div className="hstack gap-4">
          <div style={{ width: 64, height: 64 }}>
            <Image
              className="rounded-circle object-fit-contain"
              src={getUserAvatar(parentReplyItem.user, metadata).smallAvatarUrl}
              alt={parentReplyItem.user.alias}
              width={64}
              height={64}
              placeholder="blur"
              blurDataURL={env.APP_BLUR_DATA_URL}
            />
          </div>

          <div className="vstack">
            <div className="mb-4">
              <div
                dangerouslySetInnerHTML={{
                  __html: parentReplyItem.reply.content ?? '',
                }}
              ></div>
            </div>

            <div>
              {path.user && (
                <>
                  <a
                    className="user-select-none text-secondary link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
                    data-bs-toggle="collapse"
                    href={`#yw-r-p-${parentReplyItem.reply.id}`}
                    role="button"
                    aria-expanded="false"
                    aria-controls={`yw-r-p-${parentReplyItem.reply.id}`}
                  >
                    {translatedFields.reply}
                  </a>
                  &nbsp;
                </>
              )}
              <Link
                href={`/users/${parentReplyItem.user.id}`}
                className="text-secondary link-body-emphasis link-offset-3 link-underline-opacity-0 link-underline-opacity-100-hover"
              >
                {parentReplyItem.user.alias}
              </Link>
              &nbsp;
              <span className="text-secondary">·</span>
              &nbsp;
              <span className="text-secondary">
                <time dateTime={parentReplyItem.reply.createdOn}>
                  {parentReplyItem.reply._createdOnText}
                </time>
              </span>
            </div>

            {path.user && (
              <div
                className="collapse"
                id={`yw-r-p-${parentReplyItem.reply.id}`}
              >
                <div>
                  <textarea
                    className="form-control my-3"
                    rows={4}
                    placeholder={translatedFields.enterReply}
                    name="replyContent"
                    value={replyContent}
                    onChange={onChangeReplyContent}
                  ></textarea>
                  <button
                    disabled={
                      createChildReplyMutation.isLoading || !replyContent
                    }
                    onClick={onClickPostReply}
                    type="button"
                    className="btn btn-outline-primary my-3 w-100"
                  >
                    {createChildReplyMutation.isLoading ? (
                      <Spinner classs="me-2" />
                    ) : (
                      <i className="bi bi-cursor me-2"></i>
                    )}
                    {translatedFields.postReply}
                  </button>
                </div>
              </div>
            )}
          </div>
        </div>

        {pages.length > 0 && (
          <div className="mx-5 vstack gap-4">
            {pages.map((item, index) => {
              return (
                <ChildReply
                  key={item.reply.id}
                  query={replyQuery}
                  childReplyItem={item}
                  childReplyIndex={index}
                  parentReplyItem={parentReplyItem}
                  parentReplyIndex={parentReplyIndex}
                  replyItem={replyItem}
                  replyIndex={replyIndex}
                  commentItem={commentItem}
                  commentIndex={commentIndex}
                />
              );
            })}
          </div>
        )}

        {replyQuery.hasNextPage && (
          <LoadMoreReplyBtn
            isLoading={replyQuery.isLoading}
            onClickLoadMore={onClickLoadMore}
          />
        )}
      </div>
    </PostIdPageContext.Provider>
  );
}

const LoadMoreReplyBtn = ({
  onClickLoadMore,
  isLoading,
}: {
  onClickLoadMore: () => void;
  isLoading: boolean;
}) => {
  return (
    <div className="row mx-0">
      <div className="col px-0">
        <div className="card border-0">
          <div className="card-body">
            <button
              onClick={onClickLoadMore}
              disabled={isLoading}
              type="button"
              className="btn rounded-pill text-secondary-emphasis w-100"
            >
              {isLoading ? <Spinner /> : <i className="bi bi-three-dots"></i>}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};
